﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using Microsoft.SharePoint.Client;
using Axelerate.Silverlight3D.Media.Media3D;

namespace SharePointTagCloud.Silverlight
{
    public partial class MainPage : UserControl
    {
        private int NumberOfTags = 25;
        private int MaxWeighting = 100;
        private string linkDetails = "http://feeds.feedburner.com/ProjectServerBlogs?format=xml";
        private string tagCloudType = "RSSTagData";
        private Microsoft.SharePoint.Client.Web _web;
        private Microsoft.SharePoint.Client.List _list;
        private List<Tag3D> tagBlocks;
        private RotateTransform3D rotateTransform;
        private bool runRotation;
        private ITagData dataForTagCloud;

        public MainPage()
        {
            InitializeComponent();
            
            HtmlElement numTagsElement = HtmlPage.Document.GetElementById("tagCloud_NumberOfTags");
            if (numTagsElement != null)
            { NumberOfTags = int.Parse(numTagsElement.GetProperty("innerHTML").ToString()); }

            HtmlElement linkDetailsElement = HtmlPage.Document.GetElementById("tagCloud_LinkDetails");
            if (linkDetailsElement != null)
            { linkDetails = linkDetailsElement.GetProperty("innerHTML").ToString(); }

            HtmlElement tagCloudTypeElement = HtmlPage.Document.GetElementById("tagCloud_TagCloudType");
            if (tagCloudTypeElement != null)
            { tagCloudType = tagCloudTypeElement.GetProperty("innerHTML").ToString(); }

            HtmlElement maxWeightingElement = HtmlPage.Document.GetElementById("tagCloud_MaxWeightingElement");
            if (maxWeightingElement != null)
            { MaxWeighting = int.Parse(maxWeightingElement.GetProperty("innerHTML").ToString()); }

            LoadTags(NumberOfTags, linkDetails, tagCloudType, MaxWeighting);
            //http://feeds.feedburner.com/nmecom/rss/newsxml?format=xml
            
        }

        public void LoadTags(int NumberOfTags, string LinkDetails, string TagCloudType, int MaxWeighting)
        {
            this.MaxWeighting = MaxWeighting;
            this.NumberOfTags = NumberOfTags;

            /*
            dataForTagCloud = new SharePointCOMTagData();
            dataForTagCloud.LinkDetails = "Tasks";
             */
            switch (TagCloudType)
            {
                case "SharePointCOMTagData":
                    dataForTagCloud = new SharePointCOMTagData();
                    break;
                case "RSSTagData":
                    dataForTagCloud = new RSSTagData();
                    break;
                default:
                    dataForTagCloud = new RSSTagData();
                    break;
            }
            
            dataForTagCloud.LinkDetails = LinkDetails;
            dataForTagCloud.DataLoaded += new DataLoadEvent(dataForTagCloud_DataLoaded);
            dataForTagCloud.GetData();
        }

        void dataForTagCloud_DataLoaded()
        {
            Dispatcher.BeginInvoke(FillList);
        }

        private void FillList()
        {
           
            FillTags();
            rotateTransform = new RotateTransform3D();
            rotateTransform.Rotation = new AxisAngleRotation3D(new Vector3D(1.0, 0.0, 0.0), 0);
            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
            LayoutRoot.MouseEnter += new MouseEventHandler(LayoutRoot_MouseEnter);
            LayoutRoot.MouseLeave += new MouseEventHandler(LayoutRoot_MouseLeave);
        }

        private void FillTags()
        {
            tagBlocks = new List<Tag3D>();
            var sortedDict = (from entry in dataForTagCloud.tags orderby entry.Value descending select entry).Take(NumberOfTags);

            double radius = RootCanvas.Width / 3;
            int max = sortedDict.Count();
            double phi = 0;
            double theta = 0;

            int i = 1;
            
            foreach (KeyValuePair<string, int> key in sortedDict)
            {
                phi = Math.Acos(-1.0 + (2.0 * i - 1.0) / max);
                theta = Math.Sqrt(max * Math.PI) * phi;
                double x = radius * Math.Cos(theta) * Math.Sin(phi);
                double y = radius * Math.Sin(theta) * Math.Sin(phi);
                double z = radius * Math.Cos(phi);

                int weight = key.Value;
                if (weight > MaxWeighting)
                { weight = MaxWeighting; }

                Color color = new Color();

                color.R = Convert.ToByte(Math.Round(209.0 * (weight / MaxWeighting)));

                color.G = Convert.ToByte(Math.Round(18.0 * (weight / MaxWeighting)));

                color.B = Convert.ToByte(Math.Round(65.0 * (weight / MaxWeighting)));

                Tag3D tag = new Tag3D(x, y, z, key.Key.ToString() + " (" + key.Value.ToString() + ")", color);
                tag.Redraw(RootCanvas.Width / 2, RootCanvas.Height / 2);
                tag.btnLink.Click += new RoutedEventHandler(btnLink_Click);
                tag.btnLink.Tag = key.Key.ToString();
                RootCanvas.Children.Add(tag.btnLink);
                tagBlocks.Add(tag);
                i++;
            }
        }

        void btnLink_Click(object sender, RoutedEventArgs e)
        {
            HyperlinkButton btnLink = sender as HyperlinkButton;
            var linksListCollection = from tagLink in dataForTagCloud.tagLinks
                                      where tagLink.Keyword == btnLink.Tag.ToString()
                                      select tagLink;
            listLinks.Items.Clear();
            foreach (TagLink link in linksListCollection)
            {
                listLinks.Items.Add(link);
            }
            txtKeyword.Text = ((TextBlock)btnLink.Content).Text;
            RootCanvas.Visibility = System.Windows.Visibility.Collapsed;
            listPanel.Visibility = System.Windows.Visibility.Visible;
        }

        void LayoutRoot_MouseMove(object sender, MouseEventArgs e)
        {
            Point mouseLocation = e.GetPosition(RootCanvas);
            double relativeX = mouseLocation.X - (RootCanvas.ActualWidth / 2);
            double relativeY = mouseLocation.Y - (RootCanvas.ActualHeight / 2);
            MouseX.Text = relativeX.ToString();
            MouseY.Text = relativeY.ToString();
            double speed = Math.Sqrt(Math.Pow(relativeX, 2) + Math.Pow(relativeY, 2)) / 170;
            RotationSpeed.Text = speed.ToString();
            rotateTransform.Rotation = new AxisAngleRotation3D(new Vector3D(relativeY, relativeX, 0), speed);
        }

        void LayoutRoot_MouseLeave(object sender, MouseEventArgs e)
        {
            LayoutRoot.MouseMove -= LayoutRoot_MouseMove;
            runRotation = false;
        }

        void LayoutRoot_MouseEnter(object sender, MouseEventArgs e)
        {
            LayoutRoot.MouseMove += new MouseEventHandler(LayoutRoot_MouseMove);
            runRotation = true;
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            if (runRotation)
            {
                if (((AxisAngleRotation3D)rotateTransform.Rotation).Angle > 0.05)
                    RotateBlocks();
            }
        }

        private void RotateBlocks()
        {
            foreach (Tag3D textBlock in tagBlocks)
            {
                Point3D newPoint;
                if (rotateTransform.TryTransform(textBlock.centerPoint, out newPoint))
                {
                    textBlock.centerPoint = newPoint;
                    textBlock.Redraw(RootCanvas.ActualWidth / 2, RootCanvas.ActualHeight / 2);
                }
            }
        }

        private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
        {
            RootCanvas.Visibility = System.Windows.Visibility.Visible;
            listPanel.Visibility = System.Windows.Visibility.Collapsed;
        }
    }
}
